import * as Cesium from '@cesiumjs';
export {G3xObjBase} from "@g3xObjBase"
import {g3x_defineProperty, g3x_defineReadonly,track,bind} from "@g3x/utils";
import {autorun,reaction,intercept} from 'mobx';

/* 43 */
/***/
var pointDefaultOptions = {
  color: [1, 1, 0, 0.95],
  // disableDepthTestDistance,
  // distanceDisplayCondition,
  // id,
  // outlineColor,
  // outlineWidth,
  pixelSize: 6,
  position: [0, 0, 0],
  // scaleByDistance,
  show: true,
  // translucencyByDistance,
  disableDepthTestDistance: Number.POSITIVE_INFINITY
};

class G3vPoints extends G3xObjBase{
  constructor(viewer, readyCallback) {
    super();

    g3x_defineReadonly(this,'viewer', viewer)

    var _this = this;
    _this.points = [];
    _this.forcePass = undefined;
    _this._primitive = new Cesium.PointPrimitiveCollection();

    this.initUpdate()

    _this._primitiveWrapper = new Cesium.PrimitiveCollection(); // 因为PointPrimitiveCollection没有show属性，所以多包装一层
    _this._primitiveWrapper.add(_this._primitive);
    viewer.scene.primitives.add(_this._primitiveWrapper);

    _this.disposers.push(function() {
      _this._primitive && _this._primitiveWrapper.remove(_this._primitive);
      _this._primitiveWrapper && viewer.scene.primitives.remove(_this._primitiveWrapper);
    });

    _this._boundingSphere = undefined;
    
    _this.disposers.push(bind(_this, 'enabled', _this, 'show'));

    _this.disposers.push(autorun(function() {
      var show = _this.show;
      if (_this._primitiveWrapper) {
        _this._primitiveWrapper.show = show;
      }
    }));

    _this.disposers.push(reaction(function() {
      return JSON.stringify(_this.points);
    }, function() {
      _this._primitive.removeAll();
      var cartesians = [];
      var points = _this.points;
      points.forEach(function(point) {
        var _Cesium$Cartesian;
        var cp = {};
        Object.keys(pointDefaultOptions).forEach((key)=>cp[key] = point[key]);
        cp.color = new Function.prototype.bind.apply(Cesium.Color, [null,...point.color])();
        cp.position = (_Cesium$Cartesian = Cesium.Cartesian3).fromRadians.apply(_Cesium$Cartesian,[...point.position]);
        cartesians.push(cp.position);
        _this._primitive.add(cp);
      });

      _this._boundingSphere = Cesium.BoundingSphere.fromPoints(cartesians, _this._boundingSphere);
    }));

    // 还有删除属性等操作需要验证
    _this.disposers.push(intercept(_this, 'points', function(changed) {
      if (changed.type === 'update') {
        if (Array.isArray(changed.newValue)) {
          var _this$points;
          (_this$points = _this.points).splice.apply(_this$points, [0, _this.points.length, ...changed.newValue]);
        }
      }
      return undefined;
    }));

    // 数组元素改变时需要考虑
    _this.disposers.push(intercept(_this.points, function(changed) {
      if (changed.type === 'splice') {
        changed.added.forEach(function(p) {
          var np = {...pointDefaultOptions,...p};
          Object.assign(p, np)
        });
      } else if (changed.type === 'update') {
        var p = changed.newValue;
        var np = {...pointDefaultOptions,...p};
        Object.assign(p, np)
      }

      return changed;
    }));
  }

  initUpdate(){
    var _this = this;
    var that = _this;
    var ou = _this._primitive.update;
    _this._primitive.update = function(frameState) {

      // PointPrimitiveCollection绘制的深度有问题，会导致拾取位置时出错！此处通过不写depthMask来达成。
      if (!this._rsOpaque || this._rsOpaque.depthMask) {
        this._rsOpaque = Cesium.RenderState.fromCache({
          depthTest: {
            enabled: true,
            func: Cesium.WebGLConstants.LESS
          },
          depthMask: false
        });
      }

      ou.call(this, frameState);

      this._colorCommands.forEach(function(e) {
        if (that.forcePass) {
          e.originPass = e.originPass || e.pass;
          e.pass = that.forcePass;
        } else if (e.originPass && e.originPass !== e.pass) {
          e.pass = e.originPass;
          e.originPass = undefined;
        }
      });
    }
  }

  get(){
    return this._boundingSphere;
  }

  flyTo(){
    var camera = this.viewer.scene.camera;
    camera.flyToBoundingSphere(this._boundingSphere);
  }

  destroy(){
    console.log("destroy G3vPoints")
  }
}
